package server;

import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

import util.CalSerializer;
import vo.Cal;
import vo.Task;
import vo.TaskList;

public class TaskManagerTCPServer {

	private static final int WAITING = 0;
	private static final int GET_REQUESTED = 1;
	private static final int POST_REQUESTED = 2;
	private static final int PUT_REQUESTED = 3;
	private static final int DELETE_REQUESTED = 3;

	/**
	 * @param args
	 */

	public static void main(String[] args) {

		// load cal from XML-file 
		String file = "src/task-manager-xml.xml";

		Cal cal = new Cal();

		try {
			cal = CalSerializer.unMarshallCal(file);
			// ArrayList<Task> taskList =  (ArrayList<Task>)cal.tasks;
			// ArrayList<User> userList = (ArrayList<User>)cal.users;

			System.out.println("Cal DeSerialized and loaded");

		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		ServerSocket serverSocket = null;

		// Open Connection 
		try {
			serverSocket = new ServerSocket(7896);
			System.out.println("Server started");

		} 
		catch (IOException e) {
			System.out.println("Could not listen on port: 7896");
			System.exit(-1);
		}

		Socket clientSocket = null;

		try {

			System.out.println("listening..");
			clientSocket = serverSocket.accept();
		} 
		catch (IOException e) {
			System.out.println("Accept failed: 7896");
			System.exit(-1);
		}

		// Get the inputstream to receive data sent by client. 
		InputStream in;
		try {
			in = clientSocket.getInputStream();

			// based on the type of data we want to read, we will open suitable input stream.  
			DataInputStream dataIn = new DataInputStream(in);

			DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());

			String message = dataIn.readUTF().toLowerCase().trim();
			int state = WAITING;

			while (!(message.equalsIgnoreCase("exit"))) {

				System.out.println("Incoming " + message);


				if ( state == WAITING){
					if (message.equalsIgnoreCase("get")) {
						state = GET_REQUESTED;
						message = "GET";
					}

					else if (message.equalsIgnoreCase("post")) {
						state = POST_REQUESTED;
						message = "POST";
					}

					else if (message.equalsIgnoreCase("put")) {
						state = PUT_REQUESTED;
						message = "PUT";
					}

					else if (message.equalsIgnoreCase("delete")) {
						state = DELETE_REQUESTED;
						message = "DELETE";
					}

					else { message = "Illegal command - please try again"; }

				} 

				else 

				{
					// Ready for GET operation
					if ( state == GET_REQUESTED) {

						// Receive user id from client
						String userId = message;

						// Check if valid user
						if (!cal.containsUser(userId)) {
							state = WAITING;
							message = "Error";

						} else {

							//retrieve tasklist for user and marshall for transmission

							TaskList tList = cal.getUserTaskList(userId);

							if (tList != null) message = CalSerializer.marshallTaskList(tList);
							else message = "Error";

						}

						// Return to wait state
						state = WAITING;	
					}

					else if ( state == POST_REQUESTED) {

						Task t = CalSerializer.unMarshallTask(message);

						if (cal.addTask(t)) { 
							message = "Task posted";
							// save Cal to file
							SaveFile(CalSerializer.marshallCal(cal), file);
						}

						else message = "error";

						state = WAITING;
					}

					else if ( state == PUT_REQUESTED) {

						Task t = CalSerializer.unMarshallTask(message);

						if (cal.updateTask(t)) { 
							message = "Task updated";
							// save Cal to file
							SaveFile(CalSerializer.marshallCal(cal), file);
						}

						else message = "error";
						state = WAITING;
					}

					else if ( state == DELETE_REQUESTED) {
												
						if (cal.deleteTask(message)) { 
						
							message = "Task deleted";
							// save Cal to file
							
							SaveFile(CalSerializer.marshallCal(cal), file);
						}
						
						else message = "error";
						state = WAITING;
					}
				}

				System.out.println("Outgoing: " + message);

				outputStream.writeUTF(message);
				outputStream.flush();

				message = dataIn.readUTF().toLowerCase().trim();

			}

			// When client command exit
			outputStream.writeUTF("Goodbye!");
			outputStream.flush();

			clientSocket.close();
			serverSocket.close();
		}
		catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}


	}

	private static void SaveFile(String xml, String path) throws IOException {


		File file = new File(path);

		// create a bufferedwriter to write Xml
		BufferedWriter output = new BufferedWriter(new FileWriter(file));

		output.write(xml);

		output.close();

	}

}
